import { Injectable } from '@nestjs/common';

/**
 * 深度克隆工具类
 * 统一管理深度克隆功能，避免重复实现
 * 对应 Java: ObjectUtils.clone()
 */
@Injectable()
export class CloneUtil {
  /**
   * 深度克隆对象
   * @param obj 要克隆的对象
   * @returns 克隆后的对象
   */
  deepClone<T = any>(obj: T): T {
    if (obj === null || typeof obj !== 'object') {
      return obj;
    }

    if (obj instanceof Date) {
      return new Date(obj.getTime()) as any;
    }

    if (obj instanceof Array) {
      return obj.map((item) => this.deepClone(item)) as any;
    }

    if (typeof obj === 'object') {
      const clonedObj = {} as any;
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          clonedObj[key] = this.deepClone(obj[key]);
        }
      }
      return clonedObj;
    }

    return obj;
  }

  /**
   * 使用 JSON 序列化进行深度克隆
   * 性能更好，但有限制（不能克隆函数、undefined、Symbol等）
   * @param obj 要克隆的对象
   * @returns 克隆后的对象
   */
  jsonClone<T = any>(obj: T): T {
    try {
      return JSON.parse(JSON.stringify(obj));
    } catch (error) {
      throw new Error(`Failed to clone object using JSON: ${error.message}`);
    }
  }

  /**
   * 浅克隆对象
   * @param obj 要克隆的对象
   * @returns 克隆后的对象
   */
  shallowClone<T = any>(obj: T): T {
    if (obj === null || typeof obj !== 'object') {
      return obj;
    }

    if (obj instanceof Array) {
      return [...obj] as any;
    }

    if (typeof obj === 'object') {
      return { ...obj };
    }

    return obj;
  }

  /**
   * 克隆数组
   * @param arr 要克隆的数组
   * @returns 克隆后的数组
   */
  cloneArray<T>(arr: T[]): T[] {
    if (!Array.isArray(arr)) {
      throw new Error('Input is not an array');
    }
    return arr.map((item) => this.deepClone(item));
  }

  /**
   * 克隆对象并过滤指定属性
   * @param obj 要克隆的对象
   * @param excludeKeys 要排除的属性名数组
   * @returns 克隆后的对象
   */
  cloneExclude<T = any>(obj: T, excludeKeys: string[]): T {
    const cloned = this.deepClone(obj);

    if (typeof cloned === 'object' && cloned !== null) {
      for (const key of excludeKeys) {
        delete (cloned as any)[key];
      }
    }

    return cloned;
  }

  /**
   * 克隆对象并只保留指定属性
   * @param obj 要克隆的对象
   * @param includeKeys 要保留的属性名数组
   * @returns 克隆后的对象
   */
  cloneInclude<T = any>(obj: T, includeKeys: string[]): Partial<T> {
    const cloned = this.deepClone(obj);
    const result: any = {};

    if (typeof cloned === 'object' && cloned !== null) {
      for (const key of includeKeys) {
        if (key in cloned) {
          result[key] = (cloned as any)[key];
        }
      }
    }

    return result;
  }

  /**
   * 检查对象是否可克隆
   * @param obj 要检查的对象
   * @returns 是否可克隆
   */
  isCloneable(obj: any): boolean {
    if (obj === null || typeof obj !== 'object') {
      return true;
    }

    // 检查是否包含不可序列化的内容
    try {
      JSON.stringify(obj);
      return true;
    } catch (error) {
      return false;
    }
  }

  /**
   * 安全克隆（如果不可克隆则返回原对象）
   * @param obj 要克隆的对象
   * @returns 克隆后的对象或原对象
   */
  safeClone<T = any>(obj: T): T {
    if (!this.isCloneable(obj)) {
      return obj;
    }
    return this.deepClone(obj);
  }
}
